#if !defined(MIX_OS) && !defined(MIX_RTK)

#include "k_kit.h"

#include "sys_init.h"

#include <string.h>
#include <stdio.h>

#define _INIT_EXPORT_LEADER(NAME, LEVEL, PRIOR)                           \
    static int __sys_init_fn_##NAME(void)                                 \
    {                                                                     \
        return 0;                                                         \
    }                                                                     \
    __used __section(".s_sys_init_t." #LEVEL "." #PRIOR) sys_init_t const \
        __sys_init_##NAME = {                                             \
            .fn = __sys_init_fn_##NAME,                                   \
            .fn_name = #NAME,                                             \
            .line = __LINE__,                                             \
            .file = __FILE__,                                             \
            .level = LEVEL,                                               \
            .prior = PRIOR,                                               \
    }

#define _MODULE_EXPORT_LEADER(LEVEL)                            \
    __used __section(".sys_module_data." #LEVEL) module_t const \
        __sys_module_leader_##LEVEL = {                         \
            .name = "__sys_module_leader_" #LEVEL,              \
            .obj = NULL,                                        \
            .type = (module_type_t)~0,                          \
            .line = __LINE__,                                   \
            .file = __FILE__,                                   \
    }

_INIT_EXPORT_LEADER(leader_0, 0, 0);  // sys_init_t __sys_init_leader_0
_INIT_EXPORT_LEADER(leader_1, 1, 0);  // sys_init_t __sys_init_leader_1
_INIT_EXPORT_LEADER(leader_e, 9, 99); // sys_init_t __sys_init_leader_e

_MODULE_EXPORT_LEADER(0); // module_t __sys_module_leader_0
_MODULE_EXPORT_LEADER(9); // module_t __sys_module_leader_9

#define _TRUE true
#define _FALSE false

static void _sys_init(const sys_init_t *start, const sys_init_t *end)
{
    while (start < end)
    {
        start->fn();
        start = &start[1];
    }
}

__weak int app_main(void)
{
    // _DBG_WRN("no app to run");
    return -1;
}

static void _work_app_main(void *arg)
{
    static uint8_t init_flag = 0;
    if (init_flag == 0)
    {
        init_flag = 1;
        _sys_init(&__sys_init_leader_1, &__sys_init_leader_e);
    }
    app_main();
}

/**
 * @brief 初始化并进入微内核模式
 *
 * @param init_struct 初始化参数
 */
void k_entry(const k_init_t *init_struct)
{
    _sys_init(&__sys_init_leader_0, &__sys_init_leader_1);

    if (k_work_q_is_valid(default_work_q_hdl) != _FALSE)
    {
        k_work_q_delete(default_work_q_hdl);
    }
    k_deinit();
    k_init(init_struct);

    k_timer_q_create(default_timer_q_hdl);
    k_work_q_create(default_work_q_hdl);

    static k_work_t _work_hdl_init;
    k_work_create(&_work_hdl_init, "work-main", _work_app_main, NULL, 3);
    k_work_submit(default_work_q_hdl, &_work_hdl_init, 0);

    for (;;)
    {
        if (k_timer_q_handler(default_timer_q_hdl))
            k_work_q_handler(default_work_q_hdl);
    }
}

/* 自动启动 shell ------------------------------------------------------------------ */

#if defined(MIX_SHELL)

#include "kk.h"
#include "sh.h"
#include "board_config.h"

#if defined(MIX_DRV_LINUX)

static kk_work_t s_work_handler_shell;

static void _isr_console(void)
{
    kk_work_submit(WORK_Q_HDL, &s_work_handler_shell, 0);
}

static void _work_sh(void *arg)
{
    char c;
    while (drv_uart_poll_read(g_board_uart_cons.id, &c) > 0)
    {
        sh_putc(&g_uart_handle_vt100, c);
    }
    kk_work_later(10);
}

static int _create_shell_work(void)
{
    kk_work_create(&s_work_handler_shell, _work_sh, NULL, 0);
    kk_work_submit(WORK_Q_HDL, &s_work_handler_shell, 0);

    drv_uart_irq_callback_enable(g_board_uart_cons.id, _isr_console);
    drv_uart_irq_enable(g_board_uart_cons.id, true, false, 15);
    return 0;
}
INIT_EXPORT_APP(_create_shell_work, 0);

#else

static kk_work_t s_work_handler_shell;
static k_pipe_t s_pipe_handle_shell;

static void _isr_console(void)
{
    if (kk_pipe_is_valid(&s_pipe_handle_shell))
    {
        char c;
        while (drv_uart_poll_read(g_board_uart_cons.id, &c) > 0)
        {
            kk_pipe_poll_write(&s_pipe_handle_shell, c);
        }
    }
}

static void _work_sh(void *arg)
{
    uint8_t c;
    while (kk_pipe_poll_read(&s_pipe_handle_shell, &c) > 0)
    {
        sh_putc(&g_uart_handle_vt100, c);
    }
}

static int _create_shell_work(void)
{
    kk_work_create(&s_work_handler_shell, _work_sh, NULL, 0);
    kk_work_submit(WORK_Q_HDL, &s_work_handler_shell, 0);

    kk_pipe_create(&s_pipe_handle_shell, 64);
    kk_pipe_regist(&s_pipe_handle_shell, &s_work_handler_shell, 0);

    drv_uart_irq_callback_enable(g_board_uart_cons.id, _isr_console);
    drv_uart_irq_enable(g_board_uart_cons.id, true, false, 15);
    return 0;
}
INIT_EXPORT_APP(_create_shell_work, 0);

#endif

static int _show_shell_ver(void)
{
    sh_set_prompt(&g_uart_handle_vt100, "sh:/> ");
    sh_putstr_quiet(&g_uart_handle_vt100, "sh version");
    sh_putc(&g_uart_handle_vt100, '\r');
    return 0;
}
_INIT_EXPORT(_show_shell_ver, 9, 98);

#endif /* #if defined(MIX_SHELL) */

#endif /* #if !defined(MIX_OS) && !defined(MIX_RTK) */
